package procsim;

public class Encoder implements Element{
    private Signal[] inSig;
    private MSignal inSigM, result;
    private Signal enable = new Signal(1), W;
    protected int inNum;
    private int outNum, inP=0;
    protected boolean enableNotSet = true;
    protected String name = "CD";
    public Encoder(int num){
        inNum=Util.roundToNextMultiple(num); // zaokruzivanje na sledeci stepen dvojke
        outNum=(int)Math.getExponent(inNum); // broj izlaznih signala je ld(inNum)
        inSig=new Signal[inNum];
        result=new MSignal(outNum, 0);
    }
    public Encoder(int number, Signal in[]){
        this(number);
        for(int i=0; i<inNum; i++, inP++){
            in[i].addElement(this);
            if(inSig[i]!=null) inSig[i]=in[i];
        }
    }
    public Encoder(int number, MSignal in){
        this(number);
        if(in!=null) in.addElement(this);
        inSigM=in;
    }
    public Encoder add(Signal sig){
        if(inSigM!=null) // Ne mesamo babe i zabe
            System.err.println("Ne mogu se dodati novi signali");
        else if(inP<inNum){
            if(sig!=null) sig.addElement(this);
            inSig[inP++]=sig;
        }
        else
            System.err.println("Nema vise mesta za nove signale");
        return this;
    }
    public Encoder setIn(MSignal sig){
        if(sig!=null) sig.addElement(this);
        inSigM=sig;
        return this;
    }
    public Encoder setResult(MSignal sig){
        result=sig;
        return this;
    }
    public Encoder setEnableBit(Signal sig){
        if(sig!=null) sig.addElement(this);
        enable = sig;
        enableNotSet = false;
        return this;
    }
    public Encoder setWBit(Signal sig){
        if(sig!=null) sig.addElement(this);
        W = sig;
        return this;
    }
    public void setName(String name){
        this.name = name;
    }
    @Override
    public Encoder tick(){
        if(enable!=null && enable.isNull()){
            result.set(0);
            return this;
        }
        Signal[] sigarray;
        if(inSigM==null)
            sigarray=inSig;
        else
            sigarray=inSigM.getBits();
        int array[] = Util.reverseIntArray(Util.signalArray2IntArray(sigarray));
        for(int i=0; i<array.length; i++)
            if(array[array.length-1-i]==1){
                if(result!=null) result.set(new MSignal(Util.intArray2SignalArray(Util.int2BinaryArray(i, outNum))));
                if(W!=null) W.set(1);
                return this;
            }
        if(result!=null)
            result.set(new MSignal(Util.intArray2SignalArray(Util.int2BinaryArray(0, outNum))));
        if(W!=null) W.set(0);
        return this;
    }
    @Override
    public MSignal result(){
        return result;
    }
    @Override
    public String toString(){
        return ""+result;
    }
    @Override
    public void updateSignal(Sig sig) {
        boolean changed = false;
        if(inSigM!=null && inSigM==sig){
            inSigM.set(sig.get(), false);
            changed = true;
        }
        if(enable!=null && enable==sig){
            enable.set(sig.get(), false);
            changed = true;
        }
        for(int i=0; i<inSig.length; i++){
            if(inSig[i]!=null && inSig[i]==sig){
                inSig[i].set(sig.get(), false);
                changed = true;
            }
        }
        if(changed) tick();
    }
}
